﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

using Buddy.Swtor;


// BuddyWing requires the methods that implement a CC Routine to be available statically.
// This means that much of the data the use must also be available statically.  Static initialization
// in most languages is a tricky thing.  C# does us the favor of guaranteeing that static
// initialization will occur from 'top to bottom' in a given file.  C# is silent on how static
// initialization occurs across multiple files in an assembly.
// Thus, we define all the static data needed for class mirroring in this one file.  The higher level
// code should not access this data directly, but use an appropriate Mirror class method to fulfill
// its needs.
namespace WingIt.Routines.Mirrors
{
    [RevisionControlId("$Id: MirrorData.cs 705 2012-11-11 22:54:47Z Chinajade $")]
    public class MirrorData
    {
        // General rules for maintenance...
        // * Please keep things sorted alphabetically as much as possible.
        // * If an Ability/Buff/Debuff is advanced-spec specific, then use the Advanced spec to identify it.
        // * If an Ability/Buff/Debuff is common to all advanced-specs, use the Basic spec to identify it.

        #region AgentSmuggler
        // Tables built from:
        // * http://www.torhead.com/abilities/class/4/level/1-50 (Agent)
        // * http://www.torhead.com/abilities/class/7/level/1-50 (Smuggler)
        //
        private static AbilityPair[]        AgentSmuggler_AbilityPairs   =
        {
            // Level 0
            new AbilityPair(new Agent("Field Revive"), new Smuggler("Field Revive")),
            new AbilityPair(new Agent("Infected"), new Smuggler("Infected")),
            new AbilityPair(new Agent("Revive"), new Smuggler("Revive")),
            new AbilityPair(new Agent("Revive Companion"), new Smuggler("Revive Companion")),
            new AbilityPair(new Agent("Revive Target"), new Smuggler("Revive Target")),
            new AbilityPair(new Agent("Summon Companion"), new Smuggler("Summon Companion")),
            // Level 1
            new AbilityPair(new Operative("Acid Blade"), new Scoundrel("Flechette Round")),
            new AbilityPair(new Agent("Coordination"), new Smuggler("Lucky Shots")),
            new AbilityPair(new Agent("Corrosive Grenade"), new Smuggler("Shrap Bomb")),
            new AbilityPair(new Agent("Crouch"), new Smuggler("Crouch")),
            new AbilityPair(new Agent("Cull"), new Smuggler("Wounding Shots")),
            new AbilityPair(new Sniper("Diversion"), new Gunslinger("Diversion")),
            new AbilityPair(new Sniper("EMP Discharge"), new Gunslinger("Sabotage")),
            new AbilityPair(new Agent("Explosive Probe"), new Smuggler("Sabotage Charge")),
            new AbilityPair(new Sniper("Followthrough"), new Gunslinger("Trickshot")),
            new AbilityPair(new Agent("Holoconference"), new Smuggler("Holoconference")),
            new AbilityPair(new Sniper("Interrogation Probe"), new Gunslinger("Shock Charge")),
            new AbilityPair(new Operative("Kolto Probe"), new Scoundrel("Slow-release Medpac")),
            new AbilityPair(new Operative("Laceration"), new Scoundrel("Sucker Punch")),
            new AbilityPair(new Sniper("Plasma Probe"), new Gunslinger("Incendiary Grenade")),
            new AbilityPair(new Agent("Quick Travel"), new Smuggler("Quick Travel")),
            new AbilityPair(new Sniper("Rapid Fire"), new Gunslinger("Rapid Fire")),
            new AbilityPair(new Agent("Recuperate"), new Smuggler("Recuperate")),
            new AbilityPair(new Operative("Recuperative Nanotech"), new Scoundrel("Kolto Cloud")),
            new AbilityPair(new Agent("Rifle Shot"), new Smuggler("Flurry of Bolts")),
            new AbilityPair(new Agent("Snipe"), new Smuggler("Charged Burst")),
            new AbilityPair(new Agent("Sprint"), new Smuggler("Sprint")),
            new AbilityPair(new Operative("Surgical Probe"), new Scoundrel("Emergency Medpac")),
            new AbilityPair(new Agent("Take Cover"), new Smuggler("Take Cover")),
            new AbilityPair(new Agent("Weakening Blast"), new Smuggler("Hemorrhaging Blast")),
            // Level 2
            new AbilityPair(new Agent("Shiv"), new Smuggler("Blaster Whip")),
            // Level 3
            new AbilityPair(new Agent("Fragmentation Grenade"), new Smuggler("Thermal Grenade")),
            // Level 4
            new AbilityPair(new Agent("Debilitate"), new Smuggler("Dirty Kick")),
            // Level 5
            new AbilityPair(new Agent("Corrosive Dart"), new Smuggler("Vital Shot")),
            // Level 6
            new AbilityPair(new Agent("Flash Bang"), new Smuggler("Flash Grenade")),
            // Level 8
            new AbilityPair(new Agent("Overload Shot"), new Smuggler("Quick Shot")),
            // Level 9
            new AbilityPair(new Agent("Escape"), new Smuggler("Escape")),
            // Level 10
            new AbilityPair(new Sniper("Ambush"), new Gunslinger("Aimed Shot")),
            new AbilityPair(new Operative("Backstab"), new Scoundrel("Back Blast")),
            new AbilityPair(new Agent("Emergency Fleet Pass"), new Smuggler("Emergency Fleet Pass")),
            new AbilityPair(new Operative("Kolto Injection"), new Scoundrel("Underworld Medicine")),
            new AbilityPair(new Sniper("Laze Target"), new Gunslinger("Smuggler's Luck")),
            new AbilityPair(new Operative("Stealth"), new Scoundrel("Stealth")),
            new AbilityPair(new Operative("Tactical Advantage"), new Scoundrel("Upper Hand")),
            // Level 12
            new AbilityPair(new Operative("Diagnostic Scan"), new Scoundrel("Diagnostic Scan")),
            new AbilityPair(new Sniper("Leg Shot"), new Gunslinger("Leg Shot")),
            new AbilityPair(new Agent("Slice Droid"), new Smuggler("Slice Droid")),
            new AbilityPair(new Operative("Stim Boost"), new Scoundrel("Pugnacity")),
            // Level 14
            new AbilityPair(new Agent("Adrenaline Probe"), new Smuggler("Cool Head")),
            new AbilityPair(new Operative("Kolto Infusion"), new Scoundrel("Kolto Pack")),
            // Level 15
            new AbilityPair(new Agent("Heroic Moment: Advanced Recon"), new Smuggler("Heroic Moment: All In")),
            // Level 16
            new AbilityPair(new Operative("Carbine Burst"), new Scoundrel("Blaster Volley")),
            new AbilityPair(new Sniper("Cover Pulse"), new Gunslinger("Pulse Detonator")),
            // Level 18
            new AbilityPair(new Agent("Distraction"), new Smuggler("Distraction")),
            new AbilityPair(new Sniper("Takedown"), new Gunslinger("Quickdraw")),
            // Level 20
            new AbilityPair(new Sniper("Entrench"), new Gunslinger("Hunker Down")),
            new AbilityPair(new Operative("Sleep Dart"), new Scoundrel("Tranquilizer")),
            // Level 22
            new AbilityPair(new Operative("Cloaking Screen"), new Scoundrel("Disappearing Act")),
            new AbilityPair(new Operative("Sneak"), new Scoundrel("Sneak")),
            new AbilityPair(new Sniper("Suppressive Fire"), new Gunslinger("Sweeping Gunfire")),
            // Level 24
            new AbilityPair(new Agent("Evasion"), new Smuggler("Dodge")),
            new AbilityPair(new Operative("Toxin Scan"), new Scoundrel("Triage")),
            // Level 26
            new AbilityPair(new Operative("Sever Tendon"), new Scoundrel("Tendon Blast")),
            // Level 28
            new AbilityPair(new Agent("Eviscerate"), new Smuggler("Cheap Shot")),
            new AbilityPair(new Sniper("Shatter Shot"), new Gunslinger("Flourish Shot")),
            // Level 30
            new AbilityPair(new Agent("Countermeasures"), new Smuggler("Surrender")),
            // Level 32
            new AbilityPair(new Agent("Shield Probe"), new Smuggler("Defense Screen")),
            // Level 34
            new AbilityPair(new Agent("Headshot"), new Smuggler("Headshot")),
            // Level 36
            new AbilityPair(new Operative("Hidden Strike"), new Scoundrel("Shoot First")),
            new AbilityPair(new Sniper("Series of Shots"), new Gunslinger("Speed Shot")),
            // Level 42
            new AbilityPair(new Sniper("Ballistic Shield"), new Gunslinger("Scrambling Field")),
            new AbilityPair(new Operative("Infiltrate"), new Scoundrel("Smuggle")),
            // Level 48
            new AbilityPair(new Agent("Orbital Strike"), new Smuggler("XS Freighter Flyby")),
            // Level 50
            new AbilityPair(new Operative("Resuscitation Probe"), new Scoundrel("Heartrigger Patch")),
            new AbilityPair(new Sniper("Target Acquired"), new Gunslinger("Illegal Mods")),
            // Talents
            new AbilityPair(new Sniper("Snap Shot"), new Gunslinger("Snap Shot"))
        };

        private static AbilityPair[] AgentSmuggler_BuffPairs =
        {
            // Agent / Smuggler
            new AbilityPair(new Agent("Cover"), new Smuggler("Cover")),
            new AbilityPair(new Agent("Crouch"), new Smuggler("Crouch")),

            // Sniper / Gunslinger 
            new AbilityPair(new Sniper("Laze Target"), new Gunslinger("Smuggler's Luck")),  // TODO: double-check these buff names
            new AbilityPair(new Sniper("Snap Shot"), new Gunslinger("Snap Shot")),
            new AbilityPair(new Sniper("Target Acquired"), new Gunslinger("Illegal Mods")), // TODO: double-check these buff names

            // Operative / Scoundrel
            new AbilityPair(new Operative("Acid Blade"), new Scoundrel("Flechette Round")),
            new AbilityPair(new Operative("Tactical Advantage"), new Scoundrel("Upper Hand")),
            new AbilityPair(new Operative("Kolto Probe"), new Scoundrel("Slow-release Medpac")),
        };

        private static AbilityPair[] AgentSmuggler_DebuffPairs =
        {
            // Agent / Smuggler
            new AbilityPair(new Agent("Poisoned (Tech)"), new Smuggler("Bleeding (Tech)")),

            // Sniper / Gunslinger 
            new AbilityPair(new Sniper("Armor Reduced (Physical)"), new Gunslinger("Armor Reduced (Physical)")), // TODO: double-check Gunslinger debuff name
            new AbilityPair(new Sniper("Interrogation Probe"), new Gunslinger("Shock Charge"))

            // Operative / Scoundrel
            
        };
        #endregion  // AgentSmuggler


        #region BountyHunterTrooper
        // Tables built from:
        // * http://www.torhead.com/abilities/class/3/level/1-50 (Bounty Hunter)
        // * http://www.torhead.com/abilities/class/8/level/1-50 (Trooper)
        //
        private static AbilityPair[] BountyHunterTrooper_AbilityPairs =
        {
            // Level 0
            new AbilityPair(new BountyHunter("Field Revive"), new Trooper("Field Revive")),
            new AbilityPair(new BountyHunter("Infected"), new Trooper("Infected")),
            new AbilityPair(new BountyHunter("Revive"), new Trooper("Revive")),
            new AbilityPair(new BountyHunter("Revive Companion"), new Trooper("Revive Companion")),
            new AbilityPair(new BountyHunter("Revive Target"), new Trooper("Revive Target")),
            new AbilityPair(new BountyHunter("Summon Companion"), new Trooper("Summon Companion")),
            // Level 1
            new AbilityPair(new Mercenary("Emergency Scan"), new Commando("Bacta Infusion")),
            new AbilityPair(new Powertech("Heat Blast"), new Vanguard("Energy Blast")),
            new AbilityPair(new Mercenary("Heatseeker Missiles"), new Commando("Demolition Round")),
            new AbilityPair(new BountyHunter("Holoconference"), new Trooper("Holoconference")),
            new AbilityPair(new BountyHunter("Hunter's Boon"), new Trooper("Fortification")),
            new AbilityPair(new Powertech("Hydraulic Overrides"), new Vanguard("Hold the Line")),
            new AbilityPair(new Powertech("Immolate"), new Vanguard("Fire Pulse")),
            new AbilityPair(new BountyHunter("Incendiary Missile"), new Trooper("Incendiary Round")),
            new AbilityPair(new Powertech("Jet Charge"), new Vanguard("Storm")),
            new AbilityPair(new Mercenary("Kolto Missile"), new Commando("Kolto Bomb")),
            new AbilityPair(new Mercenary("Kolto Shell"), new Commando("Trauma Probe")),
            new AbilityPair(new BountyHunter("Missile Blast"), new Trooper("Explosive Round")),
            new AbilityPair(new Powertech("Oil Slick"), new Vanguard("Smoke Grenade")),
            new AbilityPair(new BountyHunter("Quick Travel"), new Trooper("Quick Travel")),
            new AbilityPair(new BountyHunter("Rapid Shots"), new Trooper("Hammer Shot")),
            new AbilityPair(new BountyHunter("Recharge and Reload"), new Trooper("Recharge and Reload")),
            new AbilityPair(new Powertech("Rectractable Blade"), new Vanguard("Gut")),
            new AbilityPair(new BountyHunter("Sprint"), new Trooper("Sprint")),
            new AbilityPair(new Mercenary("Thermal Detonator"), new Commando("Assault Plastique")),
            new AbilityPair(new Mercenary("Tracer Missile"), new Commando("Grav Round")),
            new AbilityPair(new BountyHunter("Vent Heat"), new Trooper("Recharge Cells")),
            // Level 2
            new AbilityPair(new BountyHunter("Rocket Punch"), new Trooper("Stockstrike")),
            // Level 3
            new AbilityPair(new BountyHunter("Unload"), new Trooper("Full Auto")),
            // Level 4
            new AbilityPair(new BountyHunter("Combustible Gas Cylinder"), new Trooper("Plasma Cell")),
            // Level 5
            new AbilityPair(new BountyHunter("Explosive Dart"), new Trooper("Sticky Grenade")),
            // Level 6
            new AbilityPair(new BountyHunter("Rail Shot"), new Trooper("High Impact Bolt")),
            // Level 8
            new AbilityPair(new BountyHunter("Flame Thrower"), new Trooper("Pulse Cannon")),
            // Level 9
            new AbilityPair(new BountyHunter("Determination"), new Trooper("Tenacity")),
            // Level 10
            new AbilityPair(new BountyHunter("Death from Above"), new Trooper("Mortar Volley")),
            new AbilityPair(new BountyHunter("Emergency Fleet Pass"), new Trooper("Emergency Fleet Pass")),
            new AbilityPair(new Powertech("Flame Burst"), new Vanguard("Ion Pulse")),
            new AbilityPair(new Mercenary("Power Shot"), new Commando("Charged Bolts")),
            new AbilityPair(new Mercenary("Rapid Scan"), new Commando("Medical Probe")),
            // Level 12
            new AbilityPair(new BountyHunter("Electro Dart"), new Trooper("Cryo Grenade")),
            new AbilityPair(new Mercenary("High Velocity Gas Cylinder"), new Commando("Armor-piercing Cell")),
            new AbilityPair(new Mercenary("Sweeping Blasters"), new Commando("Hail of Bolts")),
            // Level 14
            new AbilityPair(new Mercenary("Combat Support Cylinder"), new Commando("Combat Support Cell")),
            new AbilityPair(new BountyHunter("Energy Shield"), new Trooper("Reactive Shield")),
            new AbilityPair(new Powertech("Guard"), new Vanguard("Guard")),
            new AbilityPair(new Powertech("Ion Gas Cylinder"), new Vanguard("Ion Cell")),
            new AbilityPair(new Mercenary("Jet Boost"), new Commando("Concussion Charge")),
            // Level 15
            new AbilityPair(new BountyHunter("Heroic Moment: On the Trail"), new Trooper("Heroic Moment: No Retreat")),
            // Level 16
            new AbilityPair(new Mercenary("Healing Scan"), new Commando("Advanced Medical Probe")),
            new AbilityPair(new Powertech("Neural Dart"), new Vanguard("Neural Jolt")),
            // Level 18
            new AbilityPair(new Mercenary("Fusion Missile"), new Commando("Plasma Grenade")),
            new AbilityPair(new Powertech("Quell"), new Vanguard("Riot Strike")),
            // Level 20
            new AbilityPair(new Powertech("High Energy Gas Cylinder"), new Vanguard("High Energy Cell")),
            // Level 22
            new AbilityPair(new Mercenary("Concussion Missile"), new Commando("Concussive Round")),
            new AbilityPair(new Powertech("Grapple"), new Vanguard("Harpoon")),
            // Level 24
            new AbilityPair(new Mercenary("Cure"), new Commando("Field Aid")),
            new AbilityPair(new Powertech("Flame Sweep"), new Vanguard("Explosive Surge")),
            // Level 30
            new AbilityPair(new Mercenary("Chaff Flare"), new Commando("Diversion")),
            new AbilityPair(new Powertech("Sonic Missile"), new Vanguard("Sonic Round")),
            // Level 32
            new AbilityPair(new BountyHunter("Kolto Overload"), new Trooper("Adrenaline Rush")),
            // Level 34
            new AbilityPair(new BountyHunter("Shoulder Slam"), new Trooper("Blitz")),
            // Level 36
            new AbilityPair(new BountyHunter("Stealth Scan"), new Trooper("Stealth Scan")),
            // Level 42
            new AbilityPair(new BountyHunter("Thermal Sensor Override"), new Trooper("Reserve Powercell")),
            // Level 46
            new AbilityPair(new Powertech("Carbonize"), new Vanguard("Neural Surge")),
            new AbilityPair(new Mercenary("Power Surge"), new Commando("Tech Override")),
            // Level 50
            new AbilityPair(new Powertech("Explosive Fuel"), new Vanguard("Battle Focus")),
            new AbilityPair(new Mercenary("Onboard AED"), new Commando("Emergency Medical Probe")),
            // Talents
            new AbilityPair(new Mercenary("Supercharged Gas"), new Commando("Supercharge Cells")),
        };

        private static AbilityPair[] BountyHunterTrooper_BuffPairs =
        {
            // Bounty Hunter / Trooper
            new AbilityPair(new BountyHunter("Combustible Gas Cylinder"), new Trooper("Plasma Cell")),
            new AbilityPair(new BountyHunter("Prototype Particle Accelerator"), new Trooper("Ionic Accelerator")),

            // Mercenary / Commando
            new AbilityPair(new Mercenary("Barrage"), new Commando("Curtain of Fire")),
            new AbilityPair(new Mercenary("Tracer Lock"), new Commando("Charged Barrel")),
            // NB: "Supercharge" is a 30-stacking buff, and "Supercharge Gas" is a non-stacking buff. We need both entries.
            new AbilityPair(new Mercenary("Supercharge"), new Commando("Supercharge")),
            new AbilityPair(new Mercenary("Supercharged Gas"), new Commando("Supercharge Cells")),
            new AbilityPair(new Mercenary("Kolto Shell"), new Commando("Trauma Probe")),

            // Powertech / Vanguard
            new AbilityPair(new Powertech("Charged Gauntlets"), new Vanguard("Combat Tactics")),
	        new AbilityPair(new Powertech("Flame Barrage"), new Vanguard("Battering Ram")),
            new AbilityPair(new Powertech("Guard"), new Vanguard("Guard")),
            new AbilityPair(new Powertech("Ion Gas Cylinder"), new Vanguard("Ion Cell"))
        };

        private static AbilityPair[] BountyHunterTrooper_DebuffPairs =
        {
            // Bounty Hunter / Trooper

            // Mercenary / Commando
            new AbilityPair(new Mercenary("Heat Signature"), new Commando("Gravity Vortex"))

            // Powertech / Vanguard

        };
        #endregion  // BountyHunterTrooper



        #region InquistorConsular
        // Tables built from:
        // * http://www.torhead.com/abilities/class/2/level/1-50 (Inquisitor)
        // * http://www.torhead.com/abilities/class/6/level/1-50 (Consular)
        //
        private static AbilityPair[]     InquisitorConsular_AbilityPairs   =
        {
            // Level 0
            new AbilityPair(new Inquisitor("Attack"), new Consular("Attack")),
            new AbilityPair(new Inquisitor("Field Revive"), new Consular("Field Revive")),
            new AbilityPair(new Inquisitor("Infected"), new Consular("Infected")),
            new AbilityPair(new Inquisitor("Revive"), new Consular("Revive")),
            new AbilityPair(new Inquisitor("Revive Companion"), new Consular("Revive Companion")),
            new AbilityPair(new Inquisitor("Revive Target"), new Consular("Revive Target")),
            new AbilityPair(new Inquisitor("Summon Companion"), new Consular("Summon Companion")),
            // Level 1
            new AbilityPair(new Sorcerer("Chain Lightning"), new Sage("Telekinetic Wave")),
            new AbilityPair(new Inquisitor("Creeping Terror"), new Consular("Sever Force")),
            new AbilityPair(new Assassin("Dark Ward"), new Shadow("Kinetic Ward")),
            new AbilityPair(new Inquisitor("Death Field"), new Consular("Force in Balance")),
            new AbilityPair(new Assassin("Force Pull"), new Shadow("Force Pull")),
            new AbilityPair(new Inquisitor("Holoconference"), new Consular("Holoconference")),
            new AbilityPair(new Sorcerer("Innervate"), new Sage("Healing Trance")),
            new AbilityPair(new Assassin("Low Slash"), new Shadow("Low Slash")),
            new AbilityPair(new Inquisitor("Mark of Power"), new Consular("Force Valor")),
            new AbilityPair(new Sorcerer("Polarity Shift"), new Sage("Mental Alacrity")),
            new AbilityPair(new Inquisitor("Quick Travel"), new Consular("Quick Travel")),
            new AbilityPair(new Sorcerer("Resurgence"), new Sage("Rejuvenate")),
            new AbilityPair(new Sorcerer("Revivification"), new Sage("Salvation")),
            new AbilityPair(new Inquisitor("Saber Strike"), new Consular("Saber Strike")),
            new AbilityPair(new Inquisitor("Seethe"), new Consular("Meditation")),
            new AbilityPair(new Inquisitor("Shock"), new Consular("Project")),
            new AbilityPair(new Inquisitor("Sprint"), new Consular("Sprint")),
            new AbilityPair(new Assassin("Surging Charge"), new Shadow("Shadow Technique")),
            new AbilityPair(new Inquisitor("Thrash"), new Consular("Double Strike")),
            new AbilityPair(new Sorcerer("Thundering Blast"), new Sage("Turbulence")),
            new AbilityPair(new Assassin("Voltaic Slash"), new Shadow("Clairvoyant Strike")),
            new AbilityPair(new Assassin("Wither"), new Shadow("Slow Time")),
            // Level 2
            new AbilityPair(new Inquisitor("Force Lightning"), new Consular("Telekinetic Throw")),
            // Level 3
            new AbilityPair(new Inquisitor("Overload"), new Consular("Force Wave")),
            // Level 4
            new AbilityPair(new Inquisitor("Whirlwind"), new Consular("Force Lift")),
            // Level 6
            new AbilityPair(new Inquisitor("Electrocute"), new Consular("Force Stun")),
            // Level 8
            new AbilityPair(new Inquisitor("Recklessness"), new Consular("Force Potency")),
            // Level 9
            new AbilityPair(new Inquisitor("Unbreakable Will"), new Consular("Force of Will")),
            // Level 10
            new AbilityPair(new Sorcerer("Dark Heal"), new Sage("Benevolence")),
            new AbilityPair(new Inquisitor("Emergency Fleet Pass"), new Consular("Emergency Fleet Pass")),
            new AbilityPair(new Assassin("Lightning Charge"), new Shadow("Force Technique")),
            new AbilityPair(new Sorcerer("Lightning Strike"), new Sage("Disturbance")),
            new AbilityPair(new Assassin("Maul"), new Shadow("Shadow Strike")),
            new AbilityPair(new Assassin("Stealth"), new Shadow("Stealth")),
            // Level 12
            new AbilityPair(new Sorcerer("Dark Infusion"), new Sage("Deliverance")),
            new AbilityPair(new Assassin("Discharge"), new Shadow("Force Breach")),
            // Level 14
            new AbilityPair(new Inquisitor("Crushing Darkness"), new Consular("Mind Crush")),
            new AbilityPair(new Assassin("Dark Charge"), new Shadow("Combat Technique")),
            new AbilityPair(new Assassin("Guard"), new Shadow("Guard")),
            new AbilityPair(new Sorcerer("Static Barrier"), new Sage("Force Armor")),
            // Level 15
            new AbilityPair(new Inquisitor("Heroic Moment: Channel the Force"), new Consular("Heroic Moment: Channel the Force")),
            // Level 16
            new AbilityPair(new Sorcerer("Affliction"), new Sage("Weaken Mind")),
            new AbilityPair(new Inquisitor("Force Speed"), new Consular("Force Speed")),
            new AbilityPair(new Assassin("Mind Control"), new Shadow("Mind Control")),
            // Level 18
            new AbilityPair(new Inquisitor("Jolt"), new Consular("Mind Snap")),
            // Level 20
            new AbilityPair(new Sorcerer("Consumption"), new Sage("Noble Sacrifice")),
            new AbilityPair(new Assassin("Mind Trap"), new Shadow("Mind Maze")),
            // Level 22
            new AbilityPair(new Assassin("Blackout"), new Shadow("Blackout")),
            new AbilityPair(new Assassin("Force Cloak"), new Shadow("Force Cloak")),
            new AbilityPair(new Inquisitor("Force Slow"), new Consular("Force Slow")),
            // Level 24
            new AbilityPair(new Assassin("Deflection"), new Shadow("Deflection")),
            new AbilityPair(new Sorcerer("Purge"), new Sage("Restoration")),
            // Level 26
            new AbilityPair(new Assassin("Lacerate"), new Shadow("Whirling Blow")),
            // Level 28
            new AbilityPair(new Inquisitor("Tumult"), new Consular("Tumult")),
            // Level 30
            new AbilityPair(new Sorcerer("Cloud Mind"), new Sage("Cloud Mind")),
            new AbilityPair(new Assassin("Mass Mind Control"), new Shadow("Mass Mind Control")),
            // Level 32
            new AbilityPair(new Assassin("Assassinate"), new Shadow("Spinning Strike")),
            // Level 34
            new AbilityPair(new Sorcerer("Force Storm"), new Sage("Forcequake")),
            // Level 36
            new AbilityPair(new Assassin("Force Shroud"), new Shadow("Resilience")),
            // Level 42
            new AbilityPair(new Sorcerer("Extrication"), new Sage("Rescue")),
            new AbilityPair(new Assassin("Spike"), new Shadow("Spinning Kick")),
            // Level 50
            new AbilityPair(new Assassin("Overcharge Saber"), new Shadow("Battle Readiness")),
            new AbilityPair(new Sorcerer("Reanimation"), new Sage("Revival")),
            // Talents
            new AbilityPair(new Sorcerer("Force Surge"), new Sage("Resplendence")),
            new AbilityPair(new Assassin("Harnessed Darkness"), new Shadow("Harnessed Shadows")),
            new AbilityPair(new Assassin("Induction"), new Shadow("Circling Shadows")),
            new AbilityPair(new Sorcerer("Lightning Barrage"), new Sage("Psychic Projection")),
            new AbilityPair(new Sorcerer("Reconstruct"), new Sage("Force Shelter")),
            new AbilityPair(new Sorcerer("Subversion"), new Sage("Concentration")),
            new AbilityPair(new Sorcerer("Wrath"), new Sage("Presence of Mind")),
        };

        private static AbilityPair[]     InquisitorConsular_BuffPairs   =
        {
            // Inquisitor / Consular
            new AbilityPair(new Inquisitor("Recklessness"), new Consular("Force Potency")),

            // Sorcerer / Sage
            new AbilityPair(new Sorcerer("Force Bending"), new Sage("Conveyance")),
            new AbilityPair(new Sorcerer("Force Surge"), new Sage("Resplendence")),
            new AbilityPair(new Sorcerer("Lightning Barrage"), new Sage("Psychic Projection")),
            new AbilityPair(new Sorcerer("Lightning Storm"), new Sage("Tidal Force")),
            new AbilityPair(new Sorcerer("Reconstruct"), new Sage("Force Shelter")),
            new AbilityPair(new Sorcerer("Resurgence"), new Sage("Rejuvenate")),
            new AbilityPair(new Sorcerer("Static Barrier"), new Sage("Force Armor")),
            new AbilityPair(new Sorcerer("Subversion"), new Sage("Concentration")),
            new AbilityPair(new Sorcerer("Wrath"), new Sage("Presence of Mind")),

            // Assasin / Shadow
            new AbilityPair(new Assassin("Dark Charge"), new Shadow("Combat Technique")),
            new AbilityPair(new Assassin("Dark Embrace"), new Shadow("Shadow's Respite")),
            new AbilityPair(new Assassin("Dark Ward"), new Shadow("Kinetic Ward")),
            new AbilityPair(new Assassin("Exploit Weakness"), new Shadow("Find Weakness")),
            new AbilityPair(new Assassin("Guard"), new Shadow("Guard")),
            new AbilityPair(new Assassin("Harnessed Darkness"), new Shadow("Harnessed Shadows")),
            new AbilityPair(new Assassin("Induction"), new Shadow("Circling Shadows")),
            new AbilityPair(new Assassin("Lightning Charge"), new Shadow("Force Technique")),
            new AbilityPair(new Assassin("Overcharge Saber"), new Shadow("Battle Readiness")),
            new AbilityPair(new Assassin("Raze"), new Shadow("Force Strike")),
            new AbilityPair(new Assassin("Static Charge"), new Shadow("Exit Strategy")),
            new AbilityPair(new Assassin("Stealth"), new Shadow("Stealth")),
            new AbilityPair(new Assassin("Surging Charge"), new Shadow("Shadow Technique")),
        };

        private static AbilityPair[]     InquisitorConsular_DebuffPairs   =
        {
            // Inquisitor / Consular

            // Sorcerer / Sage
            new AbilityPair(new Sorcerer("Affliction (Force)"), new Sage("Weaken Mind (Force)")),
            new AbilityPair(new Sorcerer("Consumption"), new Sage("Noble Sacrifice")),
            new AbilityPair(new Sorcerer("Creeping Terror (Force)"), new Sage("Sever Force (Force)")),
            new AbilityPair(new Sorcerer("Deionized"), new Sage("Force-imbalance")),
            new AbilityPair(new Inquisitor("Shocked (Force)"), new Consular("Crushed (Force)")),

            // Assasin / Shadow
            new AbilityPair(new Assassin("Wither"), new Shadow("Slow Time"))    // TODO: double-check these buff names
        };
        #endregion  // InquisitorConsular


        #region WarriorKnight
        // Tables built from:
        // * http://www.torhead.com/abilities/class/1/level/1-50 (Warrior)
        // * http://www.torhead.com/abilities/class/5/level/1-50 (Knight)
        //
        private static AbilityPair[]     WarriorKnight_AbilityPairs   =
        {
            // Level 0
            new AbilityPair(new Warrior("Field Revive"), new Knight("Field Revive")),
            new AbilityPair(new Warrior("Infected"), new Knight("Infected")),
            new AbilityPair(new Warrior("Revive"), new Knight("Revive")),
            new AbilityPair(new Warrior("Revive Companion"), new Knight("Revive Companion")),
            new AbilityPair(new Warrior("Revive Target"), new Knight("Revive Target")),
            new AbilityPair(new Warrior("Summon Companion"), new Knight("Summon Companion")),
            // Level 1
            new AbilityPair(new Marauder("Annihilate"), new Sentinel("Merciless Slash")),
            new AbilityPair(new Warrior("Assault"), new Knight("Strike")),
            new AbilityPair(new Marauder("Ataru Form"), new Sentinel("Ataru Form")),
            new AbilityPair(new Juggernaut("Backhand"), new Guardian("Hilt Strike")),
            new AbilityPair(new Warrior("Channel Hatred"), new Knight("Introspection")),
            new AbilityPair(new Juggernaut("Crushing Blow"), new Guardian("Guardian Slash")),
            new AbilityPair(new Marauder("Deadly Saber"), new Sentinel("Overload Saber")),
            new AbilityPair(new Warrior("Force Crush"), new Knight("Force Exhaustion")),
            new AbilityPair(new Marauder("Gore"), new Sentinel("Precision Slash")),
            new AbilityPair(new Marauder("Fury"), new Sentinel("Centering")),
            new AbilityPair(new Warrior("Holoconference"), new Knight("Holoconference")),
            new AbilityPair(new Juggernaut("Impale"), new Guardian("Overhead Slash")),
            new AbilityPair(new Juggernaut("Invincible"), new Guardian("Warding Call")),
            new AbilityPair(new Marauder("Massacre"), new Sentinel("Blade Rush")),
            new AbilityPair(new Warrior("Obliterate"), new Knight("Zealous Leap")),
            new AbilityPair(new Warrior("Quick Travel"), new Knight("Quick Travel")),
            new AbilityPair(new Juggernaut("Shatter"), new Guardian("Plasma Brand")),
            new AbilityPair(new Warrior("Shii-Cho Form"), new Knight("Shii-Cho Form")),
            new AbilityPair(new Juggernaut("Shien Form"), new Guardian("Shien Form")),
            new AbilityPair(new Warrior("Shockwave"), new Knight("Singularity")),
            new AbilityPair(new Warrior("Sprint"), new Knight("Sprint")),
            new AbilityPair(new Warrior("Unnatural Might"), new Knight("Force Might")),
            new AbilityPair(new Warrior("Vicious Slash"), new Knight("Slash")),
            // Level 2
            new AbilityPair(new Warrior("Force Charge"), new Knight("Force Leap")),
            // Level 3
            new AbilityPair(new Warrior("Smash"), new Knight("Force Sweep")),
            // Level 4
            new AbilityPair(new Warrior("Saber Ward"), new Knight("Saber Ward")),
            // Level 5
            new AbilityPair(new Warrior("Retaliation"), new Knight("Riposte")),
            // Level 6
            new AbilityPair(new Warrior("Force Scream"), new Knight("Blade Storm")),
            // Level 8
            new AbilityPair(new Warrior("Ravage"), new Knight("Master Strike")),
            // Level 9
            new AbilityPair(new Warrior("Unleash"), new Knight("Resolute")),
            // Level 10
            new AbilityPair(new Marauder("Battering Assault"), new Sentinel("Zealous Strike")),
            new AbilityPair(new Marauder("Berserk"), new Sentinel("Zen")),
            new AbilityPair(new Marauder("Cloak of Pain"), new Sentinel("Rebuke")),
            new AbilityPair(new Warrior("Emergency Fleet Pass"), new Knight("Emergency Fleet Pass")),
            new AbilityPair(new Juggernaut("Sundering Assault"), new Guardian("Sundering Strike")),
            // Level 12
            new AbilityPair(new Juggernaut("Chilling Scream"), new Guardian("Freezing Force")),
            new AbilityPair(new Marauder("Rupture"), new Sentinel("Cauterize")),
            // Level 14
            new AbilityPair(new Juggernaut("Guard"), new Guardian("Guard")),
            new AbilityPair(new Marauder("Juyo Form"), new Sentinel("Juyo Form")),
            new AbilityPair(new Juggernaut("Soresu Form"), new Guardian("Soresu Form")),
            // Level 15
            new AbilityPair(new Warrior("Heroic Moment: Call on the Force"), new Knight("Heroic Moment: Call On the Force")),
            // Level 16
            new AbilityPair(new Marauder("Crippling Slash"), new Sentinel("Leg Slash")),
            new AbilityPair(new Juggernaut("Taunt"), new Guardian("Taunt")),
            // Level 18
            new AbilityPair(new Marauder("Deadly Throw"), new Sentinel("Crippling Throw")),
            new AbilityPair(new Warrior("Disruption"), new Knight("Force Kick")),
            // Level 22
            new AbilityPair(new Juggernaut("Enrage"), new Guardian("Combat Focus")),
            new AbilityPair(new Marauder("Predation"), new Sentinel("Transcendence")),
            // Level 24
            new AbilityPair(new Warrior("Force Choke"), new Knight("Force Stasis")),
            // Level 26
            new AbilityPair(new Juggernaut("Force Push"), new Guardian("Force Push")),
            new AbilityPair(new Marauder("Obfuscate"), new Sentinel("Pacify")),
            // Level 28
            new AbilityPair(new Marauder("Disable Droid"), new Sentinel("Disable Droid")),
            new AbilityPair(new Juggernaut("Endure Pain"), new Guardian("Enure")),
            new AbilityPair(new Warrior("Pommel Strike"), new Knight("Pommel Strike")),
            // Level 30
            new AbilityPair(new Marauder("Force Camouflage"), new Sentinel("Force Camouflage")),
            new AbilityPair(new Juggernaut("Threatening Scream"), new Guardian("Challenging Call")),
            // Level 32
            new AbilityPair(new Warrior("Sweeping Slash"), new Knight("Cyclone Slash")),
            // Level 34
            new AbilityPair(new Warrior("Savage Kick"), new Knight("Opportune Strike")),
            // Level 36
            new AbilityPair(new Juggernaut("Saber Throw"), new Guardian("Saber Throw")),
            // Level 38
            new AbilityPair(new Juggernaut("Enraged Defense"), new Guardian("Focused Defense")),
            new AbilityPair(new Marauder("Undying Rage"), new Sentinel("Guarded by the Force")),
            // Level 42
            new AbilityPair(new Warrior("Intimidating Roar"), new Knight("Awe")),
            // Level 44
            new AbilityPair(new Marauder("Bloodthirst"), new Sentinel("Inspiration")),
            // Level 46
            new AbilityPair(new Warrior("Vicious Throw"), new Knight("Dispatch")),
            // Level 50
            new AbilityPair(new Marauder("Frenzy"), new Sentinel("Valorous Call")),
            new AbilityPair(new Juggernaut("Intercede"), new Guardian("Guardian Leap")),
            // Talents
            new AbilityPair(new Juggernaut("Battle Cry"), new Guardian("Momentum")),
            new AbilityPair(new Warrior("Dominate"), new Knight("Felling Blow")),
            new AbilityPair(new Juggernaut("Ruin"), new Guardian("Effluence")),
            new AbilityPair(new Juggernaut("Savagery"), new Guardian("Force Rush")),
            new AbilityPair(new Marauder("Sever"), new Sentinel("Swift Blades")),
            new AbilityPair(new Marauder("Towering Rage"), new Sentinel("Debilitation")),
        };

        private static AbilityPair[] WarriorKnight_BuffPairs =
        {
            // Warrior / Knight
            new AbilityPair(new Warrior("Dominate"), new Knight("Felling Blow")),
            new AbilityPair(new Warrior("Force Choke"), new Knight("Force Stasis")),
            new AbilityPair(new Warrior("Saber Ward"), new Knight("Saber Ward")),
            new AbilityPair(new Warrior("Shii-Cho Form"), new Knight("Shii-Cho Form")),
            new AbilityPair(new Warrior("Shockwave"), new Knight("Singularity")),
            new AbilityPair(new Warrior("Sprint"), new Knight("Sprint")),

            // Marauder / Sentinel
            new AbilityPair(new Marauder("Ataru Form"), new Sentinel("Ataru Form")),
            new AbilityPair(new Marauder("Blood Frenzy"), new Sentinel("Combat Trance")),
            new AbilityPair(new Marauder("Cloak of Pain"), new Sentinel("Rebuke")),
            new AbilityPair(new Marauder("Deadly Saber"), new Sentinel("Overload Saber")),
            new AbilityPair(new Marauder("Force Camouflage"), new Sentinel("Force Camouflage")),
            new AbilityPair(new Marauder("Fury"), new Sentinel("Centering")),
            new AbilityPair(new Marauder("Juyo Form"), new Sentinel ("Juyo Form")),
            new AbilityPair(new Marauder("Massacre"), new Sentinel("Blade Rush")),
            new AbilityPair(new Marauder("Undying Rage"), new Sentinel("Guarded by the Force")),

            // Juggernaut / Guardian
            new AbilityPair(new Juggernaut("Battle Cry"), new Guardian("Momentum")),
            new AbilityPair(new Juggernaut("Endure Pain"), new Guardian("Enure")),
            new AbilityPair(new Juggernaut("Guard"), new Guardian("Guard")),
            new AbilityPair(new Juggernaut("Ruin"), new Guardian("Effluence")),
            new AbilityPair(new Juggernaut("Savagery"), new Guardian("Force Rush")),
            new AbilityPair(new Juggernaut("Shien Form"), new Guardian("Shien Form")),
            new AbilityPair(new Juggernaut("Soresu Form"), new Guardian("Soresu Form")),
        };

        private static AbilityPair[] WarriorKnight_DebuffPairs =
        {
            // Warrior / Knight

            // Marauder / Sentinel

            // Juggernaut / Guardian
            new AbilityPair(new Juggernaut("Sundering Assault"), new Guardian("Sundering Strike")),
            new AbilityPair(new Juggernaut("Armor Reduced"), new Guardian("Armor Reduced")),
            
        };
        #endregion  // WarriorKnight


        #region Class/Advanced Class mappings
        /// <summary>
        /// <para>Please don't access this information directly, use <c>Mirror.GetMirrorClass() instead.</c></para>
        /// </summary>
        public readonly static Dictionary<CharacterClass, CharacterClass>   Class_EmpireToRepublic
            = new Dictionary<CharacterClass, CharacterClass>()
            {
                // Boundary condition
                { CharacterClass.Unknown, CharacterClass.Unknown },

                // Basic: Empire, Republic
                { CharacterClass.Warrior, CharacterClass.Knight },
                { CharacterClass.Inquisitor, CharacterClass.Consular },
                { CharacterClass.Agent, CharacterClass.Smuggler },
                { CharacterClass.BountyHunter, CharacterClass. Trooper},

                // Advanced: Empire, Republic
                { CharacterClass.Juggernaut, CharacterClass.Guardian },
                { CharacterClass.Marauder, CharacterClass.Sentinel },
                { CharacterClass.Assassin, CharacterClass.Shadow },
                { CharacterClass.Sorcerer, CharacterClass.Sage },
                { CharacterClass.Operative, CharacterClass.Scoundrel },
                { CharacterClass.Sniper, CharacterClass.Gunslinger },
                { CharacterClass.Mercenary, CharacterClass.Commando },
                { CharacterClass.Powertech, CharacterClass.Vanguard }
            };

        /// <summary>
        /// <para>Please don't access this information directly, use <c>Mirror.GetMirrorClass()</c> instead.</para>
        /// </summary>
        public readonly static Dictionary<CharacterClass, CharacterClass>   Class_RepublicToEmpire
            = Class_EmpireToRepublic.ToDictionary(x => x.Value, x => x.Key);

        /// <summary>
        /// <para>Please don't access this information directly, use <c>Mirror.GetNormalizedClass()</c> instead.</para>
        /// </summary>
        public static Dictionary<AdvancedClass, CharacterClass>    AdvancedToCharacterClass
            = new Dictionary<AdvancedClass, CharacterClass>()
            {
                { AdvancedClass.Juggernaut, CharacterClass.Juggernaut },
                { AdvancedClass.Marauder, CharacterClass.Marauder },
                { AdvancedClass.Assassin, CharacterClass.Assassin },
                { AdvancedClass.Sorcerer, CharacterClass.Sorcerer },
                { AdvancedClass.Operative, CharacterClass.Operative },
                { AdvancedClass.Sniper, CharacterClass.Sniper },
                { AdvancedClass.Mercenary, CharacterClass.Mercenary },
                { AdvancedClass.Powertech, CharacterClass.Powertech },

                { AdvancedClass.Guardian, CharacterClass.Guardian },
                { AdvancedClass.Sentinel, CharacterClass.Sentinel },
                { AdvancedClass.Shadow, CharacterClass.Shadow },
                { AdvancedClass.Sage, CharacterClass.Sage },
                { AdvancedClass.Scoundrel, CharacterClass.Scoundrel },
                { AdvancedClass.Gunslinger, CharacterClass.Gunslinger },
                { AdvancedClass.Commando, CharacterClass.Commando },
                { AdvancedClass.Vanguard, CharacterClass.Vanguard }
            };
        #endregion  // Class/Advanced Class mappings


        //============================================================
        // Everything below this is 'derived' data...
        // The derived data is built from the information contained in the above tables.

        #region MasterMirror_AbilityMap
        /// <summary>
        /// <para>Please don't access this information directly, use <see cref="Mirror.LookupAbility()"/> method instead.</para>
        /// </summary>
        public static Dictionary<CharacterClass, Dictionary<string, string>>    MasterMirror_AbilityMap
            = new Dictionary<CharacterClass, Dictionary<string, string>>()
            {
                // Agent- & Sniper-based classes --
                { CharacterClass.Agent, BuildTableEntry(AgentSmuggler_AbilityPairs, CharacterClass.Agent) },
                { CharacterClass.Smuggler, BuildTableEntry(AgentSmuggler_AbilityPairs, CharacterClass.Smuggler) },
                { CharacterClass.Sniper, BuildTableEntry(AgentSmuggler_AbilityPairs, CharacterClass.Sniper, CharacterClass.Agent) },
                { CharacterClass.Gunslinger, BuildTableEntry(AgentSmuggler_AbilityPairs, CharacterClass.Gunslinger, CharacterClass.Smuggler) },
                { CharacterClass.Operative, BuildTableEntry(AgentSmuggler_AbilityPairs, CharacterClass.Operative, CharacterClass.Agent) },
                { CharacterClass.Scoundrel, BuildTableEntry(AgentSmuggler_AbilityPairs, CharacterClass.Scoundrel, CharacterClass.Smuggler) },

                // BountyHunter- & Trooper-based classes --
                { CharacterClass.BountyHunter, BuildTableEntry(BountyHunterTrooper_AbilityPairs, CharacterClass.BountyHunter) },
                { CharacterClass.Trooper, BuildTableEntry(BountyHunterTrooper_AbilityPairs, CharacterClass.Trooper) },
                { CharacterClass.Mercenary, BuildTableEntry(BountyHunterTrooper_AbilityPairs, CharacterClass.Mercenary, CharacterClass.BountyHunter) },
                { CharacterClass.Commando, BuildTableEntry(BountyHunterTrooper_AbilityPairs, CharacterClass.Commando, CharacterClass.Trooper) },
                { CharacterClass.Powertech, BuildTableEntry(BountyHunterTrooper_AbilityPairs, CharacterClass.Powertech, CharacterClass.BountyHunter) },
                { CharacterClass.Vanguard, BuildTableEntry(BountyHunterTrooper_AbilityPairs, CharacterClass.Vanguard, CharacterClass.Trooper) },

                // Inquisitor & Consular-based classes --
                { CharacterClass.Inquisitor, BuildTableEntry(InquisitorConsular_AbilityPairs, CharacterClass.Inquisitor) },
                { CharacterClass.Consular, BuildTableEntry(InquisitorConsular_AbilityPairs, CharacterClass.Consular) },
                { CharacterClass.Assassin, BuildTableEntry(InquisitorConsular_AbilityPairs, CharacterClass.Assassin, CharacterClass.Inquisitor) },
                { CharacterClass.Shadow, BuildTableEntry(InquisitorConsular_AbilityPairs, CharacterClass.Shadow, CharacterClass.Consular) },
                { CharacterClass.Sorcerer, BuildTableEntry(InquisitorConsular_AbilityPairs, CharacterClass.Sorcerer, CharacterClass.Inquisitor) },
                { CharacterClass.Sage, BuildTableEntry(InquisitorConsular_AbilityPairs, CharacterClass.Sage, CharacterClass.Consular) },

                // Warrior & Knight-based classes --
                { CharacterClass.Warrior, BuildTableEntry(WarriorKnight_AbilityPairs, CharacterClass.Warrior) },
                { CharacterClass.Knight, BuildTableEntry(WarriorKnight_AbilityPairs, CharacterClass.Knight) },
                { CharacterClass.Juggernaut, BuildTableEntry(WarriorKnight_AbilityPairs, CharacterClass.Juggernaut, CharacterClass.Warrior) },
                { CharacterClass.Guardian, BuildTableEntry(WarriorKnight_AbilityPairs, CharacterClass.Guardian, CharacterClass.Knight) },
                { CharacterClass.Marauder, BuildTableEntry(WarriorKnight_AbilityPairs, CharacterClass.Marauder, CharacterClass.Warrior) },
                { CharacterClass.Sentinel, BuildTableEntry(WarriorKnight_AbilityPairs, CharacterClass.Sentinel, CharacterClass.Knight) }
            };
        #endregion  // MasterMirror_AbilityMap

        #region MasterMirror_BuffMap
        /// <summary>
        /// <para>Please don't access this information directly, use <see cref="Mirror.LookupBuff()"/> method instead.</para>
        /// </summary>
        public static Dictionary<CharacterClass, Dictionary<string, string>>    MasterMirror_BuffMap
            = new Dictionary<CharacterClass, Dictionary<string, string>>()
            {
                // Agent- & Sniper-based classes --
                { CharacterClass.Agent, BuildTableEntry(AgentSmuggler_BuffPairs, CharacterClass.Agent) },
                { CharacterClass.Smuggler, BuildTableEntry(AgentSmuggler_BuffPairs, CharacterClass.Smuggler) },
                { CharacterClass.Sniper, BuildTableEntry(AgentSmuggler_BuffPairs, CharacterClass.Sniper, CharacterClass.Agent) },
                { CharacterClass.Gunslinger, BuildTableEntry(AgentSmuggler_BuffPairs, CharacterClass.Gunslinger, CharacterClass.Smuggler) },
                { CharacterClass.Operative, BuildTableEntry(AgentSmuggler_BuffPairs, CharacterClass.Operative, CharacterClass.Agent) },
                { CharacterClass.Scoundrel, BuildTableEntry(AgentSmuggler_BuffPairs, CharacterClass.Scoundrel, CharacterClass.Smuggler) },

                // BountyHunter- & Trooper-based classes --
                { CharacterClass.BountyHunter, BuildTableEntry(BountyHunterTrooper_BuffPairs, CharacterClass.BountyHunter) },
                { CharacterClass.Trooper, BuildTableEntry(BountyHunterTrooper_BuffPairs, CharacterClass.Trooper) },
                { CharacterClass.Mercenary, BuildTableEntry(BountyHunterTrooper_BuffPairs, CharacterClass.Mercenary, CharacterClass.BountyHunter) },
                { CharacterClass.Commando, BuildTableEntry(BountyHunterTrooper_BuffPairs, CharacterClass.Commando, CharacterClass.Trooper) },
                { CharacterClass.Powertech, BuildTableEntry(BountyHunterTrooper_BuffPairs, CharacterClass.Powertech, CharacterClass.BountyHunter) },
                { CharacterClass.Vanguard, BuildTableEntry(BountyHunterTrooper_BuffPairs, CharacterClass.Vanguard, CharacterClass.Trooper) },

                // Inquisitor & Consular-based classes --
                { CharacterClass.Inquisitor, BuildTableEntry(InquisitorConsular_BuffPairs, CharacterClass.Inquisitor) },
                { CharacterClass.Consular, BuildTableEntry(InquisitorConsular_BuffPairs, CharacterClass.Consular) },
                { CharacterClass.Assassin, BuildTableEntry(InquisitorConsular_BuffPairs, CharacterClass.Assassin, CharacterClass.Inquisitor) },
                { CharacterClass.Shadow, BuildTableEntry(InquisitorConsular_BuffPairs, CharacterClass.Shadow, CharacterClass.Consular) },
                { CharacterClass.Sorcerer, BuildTableEntry(InquisitorConsular_BuffPairs, CharacterClass.Sorcerer, CharacterClass.Inquisitor) },
                { CharacterClass.Sage, BuildTableEntry(InquisitorConsular_BuffPairs, CharacterClass.Sage, CharacterClass.Consular) },

                // Warrior & Knight-based classes --
                { CharacterClass.Warrior, BuildTableEntry(WarriorKnight_BuffPairs, CharacterClass.Warrior) },
                { CharacterClass.Knight, BuildTableEntry(WarriorKnight_BuffPairs, CharacterClass.Knight) },
                { CharacterClass.Juggernaut, BuildTableEntry(WarriorKnight_BuffPairs, CharacterClass.Juggernaut, CharacterClass.Warrior) },
                { CharacterClass.Guardian, BuildTableEntry(WarriorKnight_BuffPairs, CharacterClass.Guardian, CharacterClass.Knight) },
                { CharacterClass.Marauder, BuildTableEntry(WarriorKnight_BuffPairs, CharacterClass.Marauder, CharacterClass.Warrior) },
                { CharacterClass.Sentinel, BuildTableEntry(WarriorKnight_BuffPairs, CharacterClass.Sentinel, CharacterClass.Knight) }
            };
        #endregion  // MasterMirror_BuffMap

        #region MasterMirror_DebuffMap
        /// <summary>
        /// <para>Please don't access this information directly, use <see cref="Mirror.LookupDebuff()"/> method instead.</para>
        /// </summary>
        public static Dictionary<CharacterClass, Dictionary<string, string>>    MasterMirror_DebuffMap
            = new Dictionary<CharacterClass, Dictionary<string, string>>()
            {
                // Agent- & Sniper-based classes --
                { CharacterClass.Agent, BuildTableEntry(AgentSmuggler_DebuffPairs, CharacterClass.Agent) },
                { CharacterClass.Smuggler, BuildTableEntry(AgentSmuggler_DebuffPairs, CharacterClass.Smuggler) },
                { CharacterClass.Sniper, BuildTableEntry(AgentSmuggler_DebuffPairs, CharacterClass.Sniper, CharacterClass.Agent) },
                { CharacterClass.Gunslinger, BuildTableEntry(AgentSmuggler_DebuffPairs, CharacterClass.Gunslinger, CharacterClass.Smuggler) },
                { CharacterClass.Operative, BuildTableEntry(AgentSmuggler_DebuffPairs, CharacterClass.Operative, CharacterClass.Agent) },
                { CharacterClass.Scoundrel, BuildTableEntry(AgentSmuggler_DebuffPairs, CharacterClass.Scoundrel, CharacterClass.Smuggler) },

                // BountyHunter- & Trooper-based classes --
                { CharacterClass.BountyHunter, BuildTableEntry(BountyHunterTrooper_DebuffPairs, CharacterClass.BountyHunter) },
                { CharacterClass.Trooper, BuildTableEntry(BountyHunterTrooper_DebuffPairs, CharacterClass.Trooper) },
                { CharacterClass.Mercenary, BuildTableEntry(BountyHunterTrooper_DebuffPairs, CharacterClass.Mercenary, CharacterClass.BountyHunter) },
                { CharacterClass.Commando, BuildTableEntry(BountyHunterTrooper_DebuffPairs, CharacterClass.Commando, CharacterClass.Trooper) },
                { CharacterClass.Powertech, BuildTableEntry(BountyHunterTrooper_DebuffPairs, CharacterClass.Powertech, CharacterClass.BountyHunter) },
                { CharacterClass.Vanguard, BuildTableEntry(BountyHunterTrooper_DebuffPairs, CharacterClass.Vanguard, CharacterClass.Trooper) },

                // Inquisitor & Consular-based classes --
                { CharacterClass.Inquisitor, BuildTableEntry(InquisitorConsular_DebuffPairs, CharacterClass.Inquisitor) },
                { CharacterClass.Consular, BuildTableEntry(InquisitorConsular_DebuffPairs, CharacterClass.Consular) },
                { CharacterClass.Assassin, BuildTableEntry(InquisitorConsular_DebuffPairs, CharacterClass.Assassin, CharacterClass.Inquisitor) },
                { CharacterClass.Shadow, BuildTableEntry(InquisitorConsular_DebuffPairs, CharacterClass.Shadow, CharacterClass.Consular) },
                { CharacterClass.Sorcerer, BuildTableEntry(InquisitorConsular_DebuffPairs, CharacterClass.Sorcerer, CharacterClass.Inquisitor) },
                { CharacterClass.Sage, BuildTableEntry(InquisitorConsular_DebuffPairs, CharacterClass.Sage, CharacterClass.Consular) },

                // Warrior & Knight-based classes --
                { CharacterClass.Warrior, BuildTableEntry(WarriorKnight_DebuffPairs, CharacterClass.Warrior) },
                { CharacterClass.Knight, BuildTableEntry(WarriorKnight_DebuffPairs, CharacterClass.Knight) },
                { CharacterClass.Juggernaut, BuildTableEntry(WarriorKnight_DebuffPairs, CharacterClass.Juggernaut, CharacterClass.Warrior) },
                { CharacterClass.Guardian, BuildTableEntry(WarriorKnight_DebuffPairs, CharacterClass.Guardian, CharacterClass.Knight) },
                { CharacterClass.Marauder, BuildTableEntry(WarriorKnight_DebuffPairs, CharacterClass.Marauder, CharacterClass.Warrior) },
                { CharacterClass.Sentinel, BuildTableEntry(WarriorKnight_DebuffPairs, CharacterClass.Sentinel, CharacterClass.Knight) }
            };
        #endregion  // MasterMirror_DebuffMap



        #region Validation
        public static bool      ValidateMaintenance()
        {
            bool    isValid     = true;     // Yes, bitwise "&=" operators are valid with booleans, and behave as expected

            // AbilityPairs
            isValid &= Mirror.ValidateTableMaintenance(AgentSmuggler_AbilityPairs, "AgentSmuggler_AbilityPairs",
                        MasterMirror_AbilityMap, "MasterMirror_AbilityMap",
                        new [] { CharacterClass.Agent, CharacterClass.Operative, CharacterClass.Sniper },
                        new [] { CharacterClass.Smuggler, CharacterClass.Scoundrel, CharacterClass.Gunslinger });
            isValid &= Mirror.ValidateTableMaintenance(BountyHunterTrooper_AbilityPairs, "BountyHunterTrooper_AbilityPairs",
                        MasterMirror_AbilityMap, "MasterMirror_AbilityMap",
                        new [] { CharacterClass.BountyHunter, CharacterClass.Mercenary, CharacterClass.Powertech },
                        new [] { CharacterClass.Trooper, CharacterClass.Vanguard, CharacterClass.Commando });
            isValid &= Mirror.ValidateTableMaintenance(InquisitorConsular_AbilityPairs, "InquisitorConsular_AbilityPairs",
                        MasterMirror_AbilityMap, "MasterMirror_AbilityMap",
                        new [] { CharacterClass.Inquisitor, CharacterClass.Assassin, CharacterClass.Sorcerer },
                        new [] { CharacterClass.Consular, CharacterClass.Shadow, CharacterClass.Sage });
            isValid &= Mirror.ValidateTableMaintenance(WarriorKnight_AbilityPairs, "WarriorKnight_AbilityPairs",
                        MasterMirror_AbilityMap, "MasterMirror_AbilityMap",
                        new [] { CharacterClass.Warrior, CharacterClass.Juggernaut, CharacterClass.Marauder },
                        new [] { CharacterClass.Knight, CharacterClass.Guardian, CharacterClass.Sentinel });

            // BuffPairs
            isValid &= Mirror.ValidateTableMaintenance(AgentSmuggler_BuffPairs, "AgentSmuggler_BuffPairs",
                        MasterMirror_BuffMap, "MasterMirror_BuffMap",
                        new [] { CharacterClass.Agent, CharacterClass.Operative, CharacterClass.Sniper },
                        new [] { CharacterClass.Smuggler, CharacterClass.Scoundrel, CharacterClass.Gunslinger });
            isValid &= Mirror.ValidateTableMaintenance(BountyHunterTrooper_BuffPairs, "BountyHunterTrooper_BuffPairs",
                        MasterMirror_BuffMap, "MasterMirror_BuffMap",
                        new [] { CharacterClass.BountyHunter, CharacterClass.Mercenary, CharacterClass.Powertech },
                        new [] { CharacterClass.Trooper, CharacterClass.Vanguard, CharacterClass.Commando });
            isValid &= Mirror.ValidateTableMaintenance(InquisitorConsular_BuffPairs, "InquisitorConsular_BuffPairs",
                        MasterMirror_BuffMap, "MasterMirror_BuffMap",
                        new [] { CharacterClass.Inquisitor, CharacterClass.Assassin, CharacterClass.Sorcerer },
                        new [] { CharacterClass.Consular, CharacterClass.Shadow, CharacterClass.Sage });
            isValid &= Mirror.ValidateTableMaintenance(WarriorKnight_BuffPairs, "WarriorKnight_BuffPairs",
                        MasterMirror_BuffMap, "MasterMirror_BuffMap",
                        new [] { CharacterClass.Warrior, CharacterClass.Juggernaut, CharacterClass.Marauder },
                        new [] { CharacterClass.Knight, CharacterClass.Guardian, CharacterClass.Sentinel });

            // DebuffPairs
            isValid &= Mirror.ValidateTableMaintenance(AgentSmuggler_DebuffPairs, "AgentSmuggler_DebuffPairs",
                        MasterMirror_DebuffMap, "MasterMirror_DebuffMap",
                        new [] { CharacterClass.Agent, CharacterClass.Operative, CharacterClass.Sniper },
                        new [] { CharacterClass.Smuggler, CharacterClass.Scoundrel, CharacterClass.Gunslinger });
            isValid &= Mirror.ValidateTableMaintenance(BountyHunterTrooper_DebuffPairs, "BountyHunterTrooper_DebuffPairs",
                        MasterMirror_DebuffMap, "MasterMirror_DebuffMap",
                        new [] { CharacterClass.BountyHunter, CharacterClass.Mercenary, CharacterClass.Powertech },
                        new [] { CharacterClass.Trooper, CharacterClass.Vanguard, CharacterClass.Commando });
            isValid &= Mirror.ValidateTableMaintenance(InquisitorConsular_DebuffPairs, "InquisitorConsular_DebuffPairs",
                        MasterMirror_DebuffMap, "MasterMirror_DebuffMap",
                        new [] { CharacterClass.Inquisitor, CharacterClass.Assassin, CharacterClass.Sorcerer },
                        new [] { CharacterClass.Consular, CharacterClass.Shadow, CharacterClass.Sage });
            isValid &= Mirror.ValidateTableMaintenance(WarriorKnight_DebuffPairs, "WarriorKnight_DebuffPairs",
                        MasterMirror_DebuffMap, "MasterMirror_DebuffMap",
                        new [] { CharacterClass.Warrior, CharacterClass.Juggernaut, CharacterClass.Marauder },
                        new [] { CharacterClass.Knight, CharacterClass.Guardian, CharacterClass.Sentinel });

            return (isValid);
        }
        #endregion  // Validation


        #region Schema elements
        public class ClassAbility
        {
            public readonly string          AbilityName;
            public readonly CharacterClass  NormalizedClass;


            public ClassAbility(string abilityName, CharacterClass normalizedClass)
            {
                AbilityName = abilityName;
                NormalizedClass = normalizedClass;
            }
        }

        public class AbilityPair
        {
            public readonly ClassAbility    Empire;
            public readonly ClassAbility    Republic;

            public AbilityPair(ClassAbility empire,  ClassAbility republic)
            {
                Empire = empire;
                Republic = republic;
            }

            public override string  ToString()
            {
                return (string.Format("{0}({1}(\"{2}\"), {3}(\"{4}\"))",
                                      MethodBase.GetCurrentMethod().DeclaringType.Name,
                                      Empire.NormalizedClass, Empire.AbilityName, 
                                      Republic.NormalizedClass, Republic.AbilityName));
            }
        }
        #endregion  // Schema elements


        #region Helpers
        // These are convenience classes to make table assembly more readable...
        private class Agent : ClassAbility { public Agent(string abilityName) : base(abilityName, CharacterClass.Agent) {} }    
        private class Assassin : ClassAbility { public Assassin(string    abilityName) : base(abilityName, CharacterClass.Assassin) {} }
        private class BountyHunter : ClassAbility { public BountyHunter(string   abilityName) : base(abilityName, CharacterClass.BountyHunter) {} }
        private class Commando : ClassAbility { public Commando(string    abilityName) : base(abilityName, CharacterClass.Commando) {} }
        private class Consular : ClassAbility { public Consular(string    abilityName) : base(abilityName, CharacterClass.Consular) {} }
        private class Guardian : ClassAbility { public Guardian(string    abilityName) : base(abilityName, CharacterClass.Guardian) {} }
        private class Gunslinger : ClassAbility { public Gunslinger(string abilityName) : base(abilityName, CharacterClass.Gunslinger) {} }
        private class Inquisitor : ClassAbility { public Inquisitor(string   abilityName) : base(abilityName, CharacterClass.Inquisitor) {} }
        private class Juggernaut : ClassAbility { public Juggernaut(string    abilityName) : base(abilityName, CharacterClass.Juggernaut) {} }
        private class Knight : ClassAbility { public Knight(string    abilityName) : base(abilityName, CharacterClass.Knight) {} }
        private class Marauder : ClassAbility { public Marauder(string    abilityName) : base(abilityName, CharacterClass.Marauder) {} }
        private class Mercenary : ClassAbility { public Mercenary(string    abilityName) : base(abilityName, CharacterClass.Mercenary) {} }
        private class Operative : ClassAbility { public Operative(string abilityName) : base(abilityName, CharacterClass.Operative) {} }
        private class Powertech : ClassAbility { public Powertech(string    abilityName) : base(abilityName, CharacterClass.Powertech) {} }
        private class Sage : ClassAbility { public Sage(string    abilityName) : base(abilityName, CharacterClass.Sage) {} }
        private class Scoundrel : ClassAbility { public Scoundrel(string abilityName) : base(abilityName, CharacterClass.Scoundrel) {} }
        private class Sentinel : ClassAbility { public Sentinel(string    abilityName) : base(abilityName, CharacterClass.Sentinel) {} }
        private class Shadow : ClassAbility { public Shadow(string    abilityName) : base(abilityName, CharacterClass.Shadow) {} }
        private class Smuggler : ClassAbility { public Smuggler(string abilityName) : base(abilityName, CharacterClass.Smuggler) {} }
        private class Sniper : ClassAbility { public Sniper(string abilityName) : base(abilityName, CharacterClass.Sniper) {} }
        private class Sorcerer : ClassAbility { public Sorcerer(string    abilityName) : base(abilityName, CharacterClass.Sorcerer) {} }
        private class Trooper : ClassAbility  { public Trooper(string    abilityName) : base(abilityName, CharacterClass.Trooper) {} }
        private class Vanguard : ClassAbility { public Vanguard(string    abilityName) : base(abilityName, CharacterClass.Vanguard) {} }
        private class Warrior : ClassAbility { public Warrior(string   abilityName) : base(abilityName, CharacterClass.Warrior) {} }

        private static Dictionary<string, string>  BuildTableEntry(AbilityPair[] abilityPairs, params CharacterClass[] allowedClasses)
        {
            Logger.ContractRequires(() => abilityPairs != null, () => "abilityPairs != null");
            Logger.ContractRequires(() => allowedClasses.Length > 0, () => "allowedClasses.Length > 0");

            if (Mirror.IsEmpireClass(allowedClasses[0]))
                { return (abilityPairs.Where(x => allowedClasses.Contains(x.Empire.NormalizedClass)).ToDictionary(x => x.Empire.AbilityName, x => x.Republic.AbilityName)); }
            else if (Mirror.IsRepublicClass(allowedClasses[0]))
                { return (abilityPairs.Where(x => allowedClasses.Contains(x.Republic.NormalizedClass)).ToDictionary(x => x.Republic.AbilityName, x => x.Empire.AbilityName)); }

            Logger.MaintenanceError("allowedClasses recognized as neither Empire, nor Republic: {0}",
                                    string.Join(", ", allowedClasses));
            return (null);
         }
        #endregion  // Helpers
    }
}
